using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using JGSY.CMS.LowCode.Platform.Domain.Entities;
using JGSY.CMS.LowCode.Platform.Domain.Interfaces;
using JGSY.CMS.LowCode.Platform.Infrastructure.CmsDbContext;

namespace JGSY.CMS.LowCode.Platform.Infrastructure.Repositories
{
    /// <summary>
    /// 字段仓储实现
    /// </summary>
    public class FieldRepository : Repository<Field>, IFieldRepository
    {
        public FieldRepository(LowCodeDbContext context) : base(context)
        {
        }

        public async Task<List<Field>> GetByFormIdAsync(long formId)
        {
            return await _context.Fields
                .Where(f => f.ContentModelId == formId && f.IsActive == true)
                .OrderBy(f => f.Order)
                .ToListAsync();
        }

        public async Task<Field?> GetByNameAsync(long formId, string fieldName)
        {
            return await _context.Fields
                .FirstOrDefaultAsync(f => f.ContentModelId == formId && 
                                        f.Name == fieldName && 
                                        f.IsActive == true);
        }

        public async Task<List<Field>> GetByTypeAsync(string fieldType)
        {
            return await _context.Fields
                .Where(f => f.Type == fieldType && f.IsActive == true)
                .OrderBy(f => f.ContentModelId)
                .ThenBy(f => f.Order)
                .ToListAsync();
        }

        public async Task<List<Field>> GetRequiredFieldsAsync(long formId)
        {
            return await _context.Fields
                .Where(f => f.ContentModelId == formId && 
                          f.IsRequired == true && 
                          f.IsActive == true)
                .OrderBy(f => f.Order)
                .ToListAsync();
        }

        public async Task<bool> UpdateFieldOrderAsync(Dictionary<long, int> fieldOrders)
        {
            try
            {
                foreach (var (fieldId, orderIndex) in fieldOrders)
                {
                    var field = await _context.Fields.FindAsync(fieldId);
                    if (field != null)
                    {
                        field.Order = orderIndex;
                        field.UpdatedAt = DateTime.UtcNow;
                    }
                }

                await SaveChangesAsync();
                return true;
            }
            catch
            {
                return false;
            }
        }

        public async Task<bool> BatchUpdateSortOrderAsync(Dictionary<long, int> fieldOrders)
        {
            return await UpdateFieldOrderAsync(fieldOrders);
        }

        public async Task<bool> IsNameExistsAsync(long formId, string fieldName, long? excludeId = null)
        {
            var field = await _context.Fields
                .FirstOrDefaultAsync(f => f.ContentModelId == formId && 
                                        f.Name == fieldName && 
                                        f.IsActive == true &&
                                        (excludeId == null || f.Id != excludeId));
            return field != null;
        }

        public async Task<List<Field>> CloneFormFieldsAsync(long sourceFormId, long targetFormId)
        {
            var sourceFields = await GetByFormIdAsync(sourceFormId);
            var clonedFields = new List<Field>();

            foreach (var sourceField in sourceFields)
            {
                var clonedField = new Field
                {
                    ContentModelId = targetFormId,
                    Name = sourceField.Name,
                    Label = sourceField.Label,
                    Type = sourceField.Type,
                    DefaultValue = sourceField.DefaultValue,
                    Options = sourceField.Options,
                    IsRequired = sourceField.IsRequired,
                    IsActive = sourceField.IsActive,
                    Order = sourceField.Order,
                    ValidationRules = sourceField.ValidationRules,
                    Description = sourceField.Description,
                    CreatedAt = DateTime.UtcNow,
                    UpdatedAt = DateTime.UtcNow
                };

                await base.AddAsync(clonedField);
                clonedFields.Add(clonedField);
            }

            await SaveChangesAsync();
            return clonedFields;
        }

        public async Task<(bool IsValid, List<string> Errors)> ValidateFieldConfigurationAsync(Field field)
        {
            var errors = new List<string>();

            // 检查字段名称是否在同一表单中唯一
            var existingField = await _context.Fields
                .FirstOrDefaultAsync(f => f.ContentModelId == field.ContentModelId && 
                                        f.Name == field.Name && 
                                        f.Id != field.Id &&
                                        f.IsActive == true);

            if (existingField != null)
            {
                errors.Add($"字段名称 '{field.Name}' 在当前表单中已存在");
            }

            return (errors.Count == 0, errors);
        }

        public async Task<Dictionary<string, int>> GetFieldTypeStatisticsAsync()
        {
            try
            {
                var statistics = await _context.Fields
                    .Where(f => f.IsActive == true)
                    .GroupBy(f => f.Type)
                    .Select(g => new { FieldType = g.Key, Count = g.Count() })
                    .ToDictionaryAsync(x => x.FieldType, x => x.Count);

                return statistics;
            }
            catch
            {
                return new Dictionary<string, int>();
            }
        }

        public async Task<int> DeleteByFormIdAsync(long formId)
        {
            var fields = await _context.Fields
                .Where(f => f.ContentModelId == formId && f.IsActive == true)
                .ToListAsync();

            foreach (var field in fields)
            {
                field.IsActive = false; // 软删除
                field.UpdatedAt = DateTime.UtcNow;
            }

            await SaveChangesAsync();
            return fields.Count;
        }

        public async Task<string> GetFormFieldsConfigJsonAsync(long formId)
        {
            try
            {
                var fields = await GetByFormIdAsync(formId);
                var config = fields.Select(f => new
                {
                    id = f.Id,
                    name = f.Name,
                    label = f.Label,
                    type = f.Type,
                    required = f.IsRequired,
                    enabled = f.IsActive,
                    defaultValue = f.DefaultValue,
                    options = f.Options,
                    description = f.Description,
                    orderIndex = f.Order
                }).OrderBy(f => f.orderIndex);

                return System.Text.Json.JsonSerializer.Serialize(config);
            }
            catch
            {
                return "[]";
            }
        }
    }
}
